package pl.edu.agh.pros.android;

import java.util.ArrayList;

import org.ros.RosCore;
import org.ros.android.BitmapFromCompressedImage;
import org.ros.android.view.RosImageView;
import org.ros.node.DefaultNodeMainExecutor;
import org.ros.node.NodeConfiguration;
import org.ros.node.NodeListener;
import org.ros.node.NodeMainExecutor;

import pl.edu.agh.pros.android.listener.UltimateNodeListener;
import pl.edu.agh.pros.android.ros.SensorPublisher;
import pl.edu.agh.pros.gravity.GravityListener;
import pl.edu.agh.pros.gravity.GravityVO;
import sensor_msgs.CompressedImage;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;

public class ClientActivity extends Activity {

	private final String TAG = "ClientActivity";

	private RosImageView<CompressedImage> image;
	private SensorPublisher sensorPublisher;
	private RosCore rosCore;
	private NodeMainExecutor nodeMainExecutor;

	private SensorManager mSensorManager;
	private Sensor mGravity;

	private PowerManager.WakeLock wl;

	private Handler gravityHandler = new Handler() {
		GravityVO previous;

		@Override
		public void handleMessage(Message msg) {
			GravityVO t = (GravityVO) msg.obj;
			if (t != null && !t.equals(previous)) {
				// update UI
				if (sensorPublisher != null) {
					sensorPublisher.publish(Integer.toString(t.getY()) + "," + Integer.toString(t.getZ()));
				}
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Hide the window title.
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		setContentView(R.layout.client);

		mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
		mSensorManager.registerListener(new GravityListener(gravityHandler), mGravity, SensorManager.SENSOR_DELAY_GAME);

		// Getting a WakeLock. This insures that the phone does not sleep
		// while driving the robot.
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "My Tag");
		wl.acquire();
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void onResume() {
		super.onResume();

		if (!MainActivity.isConnected(getApplicationContext(),
				(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE))) {
			finish();
			return;
		}

		if (rosCore == null) {
			rosCore = RosCore.newPrivate();
		}
		rosCore.start();
		try {
			rosCore.awaitStart();
		} catch (Exception e) {
			Log.e(TAG, "Could not run rosCore", e);
			throw new RuntimeException(e);
		}

		image = (RosImageView<CompressedImage>) findViewById(R.id.image);
		image.setTopicName("/camera/image/compressed");
		image.setMessageType(sensor_msgs.CompressedImage._TYPE);
		image.setMessageToBitmapCallable(new BitmapFromCompressedImage());
		final NodeConfiguration nodeConfiguration = NodeConfiguration.newPrivate();
		nodeConfiguration.setMasterUri(rosCore.getUri());
		if (nodeMainExecutor == null) {
			nodeMainExecutor = DefaultNodeMainExecutor.newDefault();
		}

		nodeMainExecutor.execute(image, nodeConfiguration.setNodeName("imageSubscriber"),
				new ArrayList<NodeListener>() {
					private static final long serialVersionUID = 1L;
					{
						add(new UltimateNodeListener(nodeConfiguration, "/camera/image/compressed",
								sensor_msgs.CompressedImage._TYPE, false));
					};
				});

		sensorPublisher = new SensorPublisher();
		nodeMainExecutor.execute(sensorPublisher, nodeConfiguration.setNodeName("sensorPublisher"),
				new ArrayList<NodeListener>() {
					private static final long serialVersionUID = 1L;
					{
						add(new UltimateNodeListener(nodeConfiguration, "/koala/sensors", std_msgs.String._TYPE, true));
					};
				});
	}

	@Override
	protected void onPause() {
		super.onPause();
		if (nodeMainExecutor != null) {
			nodeMainExecutor.shutdownNodeMain(image);
			nodeMainExecutor.shutdownNodeMain(sensorPublisher);
			nodeMainExecutor.shutdown();
		}
		if (rosCore != null) {
			rosCore.shutdown();
			rosCore = null;
		}
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		wl.release();
	}
}
